#ifndef WINAPI_H
#define WINAPI_H
#include <windows.h>
#include "type.h"
#include "buffer.h"
class Buffer;
class WinAPI
{
public:
	static HANDLE openDisk(int8* name)
	{
		return CreateFileA(name,
						GENERIC_READ,
						FILE_SHARE_READ|FILE_SHARE_WRITE,
						NULL,
						OPEN_EXISTING,
						FILE_ATTRIBUTE_NORMAL,
						NULL);
	}
	static uint32 getWindowsFsCount();
	static void getWindowsFsStr(uint16* strs,uint32 strs_size){GetLogicalDriveStrings(strs_size,(LPWSTR)strs);}
	static void getWindowsFsIndex(uint16* root_path,STORAGE_DEVICE_NUMBER& output);
	static Buffer getWindowsFsName(uint16* root_path);
	static uint32 getDriveType(uint16* root_path){return GetDriveType((LPCWSTR)root_path);}
	static void creatDir(const wint16* name);
	static HANDLE createFile(const wint16* name);
	static void readData(HANDLE disk_handle,uint32 sector_ptr,uint32 number_of_byte,Buffer& buffer);
	static void writeData(HANDLE file_handle,Buffer& data,uint32 number_of_write);
	static void closeHandle(HANDLE handle)
	{
		CloseHandle(handle);
	}
	static void deleteFile(const wint16* name)
	{
		DeleteFileW(name);
	}
	static void utf8ToUtf16(uint8* from,uint32 from_len,Buffer& to)
	{
		int32 len=MultiByteToWideChar(CP_UTF8,0,(LPCSTR)from,from_len,NULL,0);
		to(new uint8[len*2],len*2); 
		MultiByteToWideChar(CP_UTF8,0,(LPCSTR)from,from_len,(wint16*)to.data(),len);
	}
	static HANDLE createLock()
	{
		return CreateMutex(NULL,FALSE,NULL);
	}
	static void lock(HANDLE hlock)
	{
		WaitForSingleObject(hlock,INFINITE);
	}
	static void unlock(HANDLE hlock)
	{
		ReleaseMutex(hlock);
	}
	static HANDLE createWait(){return CreateEvent(NULL,FALSE,TRUE,NULL);}
	static void cancelWait(HANDLE hevent){SetEvent(hevent);}
	static void wait(HANDLE hevent){WaitForSingleObject(hevent,INFINITE);}
	static DWORD tryWait(HANDLE hevent){return WaitForSingleObject(hevent,0);}
	static void sleep(uint32 ms){Sleep(ms);}
};
class Lock
{
	friend class State;
private:
	Lock():hlock(WinAPI::createLock()){}
	void lock() const{WinAPI::lock(hlock);}
	void unlock() const{WinAPI::unlock(hlock);}
	~Lock(){WinAPI::closeHandle(hlock);}
	HANDLE hlock;
};
class WaitEvent
{
	friend class State;
private:
	WaitEvent():hevent(WinAPI::createWait()){}
	~WaitEvent(){WinAPI::closeHandle(hevent);}
	void lock() const{WinAPI::wait(hevent);}
	void unlock() const{WinAPI::cancelWait(hevent);}
	void ensureLock() const
	{
		while(WAIT_OBJECT_0==WinAPI::tryWait(hevent))
		{
			WinAPI::cancelWait(hevent);
			WinAPI::sleep(3);
		}
	}
	HANDLE hevent;
};
#endif